package com.dataseek.iot.device.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dataseek.iot.device.entity.DeviceAttrValue;
import com.dataseek.iot.device.entity.MqttLog;
import com.dataseek.iot.device.mapper.DeviceAttValueMapper;
import com.dataseek.iot.device.service.DeviceAttValueService;
import com.dataseek.iot.device.service.DeviceListService;
import com.dataseek.iot.device.service.MqttLogService;
import com.dataseek.iot.device.vo.DeviceListVo;
import com.dataseek.iot.mqtt.service.ISendMessage;
import com.dataseek.iot.toolikit.common.enums.RspStatusEnum;
import com.dataseek.iot.toolikit.common.response.ResponseResult;
import com.dataseek.iot.toolikit.common.service.IDServiceHelper;
import com.dataseek.iot.toolikit.common.util.DateUtils;
import com.dataseek.iot.toolkit.mybatis.entity.DeviceList;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@CrossOrigin
@Slf4j
@RequestMapping("/manage")
public class DeviceListController {

//    @Value("${mqtt.url}")
//    private  String HOST;
//
//    @Value("${mqtt.username}")
//    private String username;
//
//    @Value("${mqtt.password}")
//    private String password;

    @Autowired
    private DeviceListService deviceListService;

    @Autowired
    private DeviceAttValueService deviceAttValueService;

    @Autowired
    private MqttLogService mqttLogService;

    @Autowired
    private IDServiceHelper idServiceHelper;

    @Autowired
    private DeviceAttValueMapper deviceAttValueMapper;

    @Autowired
    private ISendMessage iMqttSender;
    /**
     * 查询设备列表
     *
     * @param deviceName 设备名称
     * @param pdtCode 产品编码
     * @param ctgCode 分类编码
     * @return
     */

    @RequestMapping(value = "/query", method = RequestMethod.GET)
    public ResponseResult queryDeviceList(@RequestParam(value="page")  Integer page, @RequestParam(value="size")  Integer size, @RequestParam(value="deviceName", required=false) String deviceName, @RequestParam(value="pdtCode", required=false) String pdtCode, @RequestParam(value="ctgCode", required=false) String ctgCode  ) throws IOException {
        DeviceListVo pdtListVo = deviceListService.queryDeviceList(pdtCode,ctgCode,deviceName,page,size);
        return new ResponseResult(RspStatusEnum.SUCCESS.getCode(),RspStatusEnum.SUCCESS.getMessage(),pdtListVo);
    }
    /**
     * 查询设备属性
     *
     * @param deviceCode 设备名称
     * @param attCode 产品编码
     * @return
     */
    @RequestMapping(value = "/queryAttr", method = RequestMethod.GET)
    public ResponseResult queryAttr(@RequestParam(value="deviceCode", required=false) String deviceCode,
                                    @RequestParam(value="attCode", required=false) String attCode) throws IOException {
        List<DeviceAttrValue> deviceAttrValueList = deviceAttValueService.queryDeviceAttList(deviceCode,attCode);
        return new ResponseResult(RspStatusEnum.SUCCESS.getCode(),RspStatusEnum.SUCCESS.getMessage(),deviceAttrValueList);
    }

    /**
     * 查询设备属性历史记录
     *
     * @param deviceCode 设备名称
     * @param attCode 产品编码
     * @return
     */
    @RequestMapping(value = "/queryAttrHis", method = RequestMethod.GET)
    public ResponseResult queryAttrHis(@RequestParam(value="deviceCode", required=false) String deviceCode,
                                    @RequestParam(value="attCode", required=false) String attCode) throws IOException {
        List<DeviceAttrValue> deviceAttrValueList = deviceAttValueService.queryDeviceAttList(deviceCode,attCode);
        return new ResponseResult(RspStatusEnum.SUCCESS.getCode(),RspStatusEnum.SUCCESS.getMessage(),deviceAttrValueList);
    }
    /**
     * 修改设备列表
     *
     * @param deviceList 设备实体类
     * @return
     */

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public ResponseResult updateDeviceList(@RequestBody DeviceList deviceList) throws IOException {
        //查询设备之前的状态，如果之前的数据库状态是inactive ，现在的是active 则表示是由不激活，变成激活
        String status=deviceList.getStatus();
        long deviceId=deviceList.getId();
        //这时候需要激活订阅 report  event
        DeviceList oneDevice=deviceListService.queryOneDevice(deviceId);
        if(oneDevice.getStatus().equals("inactive")&&deviceList.getStatus().equals("active")){
            readDeviceInfo(deviceList.getPdtCode(),deviceList.getDeviceCode());
        }
        Integer code  = deviceListService.updateDeviceList(deviceList);
        //修改设备属性
        return new ResponseResult(RspStatusEnum.SUCCESS.getCode(),RspStatusEnum.SUCCESS.getMessage(),code.toString());
    }

    /**
     * 修改设备属性
     *
     * @param deviceAttrValue 设备属性
     * @return
     */

    @RequestMapping(value = "/updateAtt", method = RequestMethod.POST)
    public ResponseResult updateAtt(@RequestBody DeviceAttrValue deviceAttrValue) throws IOException {
        //修改设备属性
        Integer code  = deviceAttValueMapper.updateById(deviceAttrValue);
        //发送修改设备属性的mqtt的topic信息
        String productId=deviceAttrValue.getPdtCode();
        String deviceId=deviceAttrValue.getDeviceCode();
        Map Properties=new HashMap();
        Properties.put(deviceAttrValue.getAttCode(),deviceAttrValue.getAttValue());
        writeDeviceInfo(productId,deviceId,Properties);
        return new ResponseResult(RspStatusEnum.SUCCESS.getCode(),RspStatusEnum.SUCCESS.getMessage(),code.toString());
    }

    /**
     * 新建设备
     *
     * @param deviceList 设备实体类
     * @return
     */

    @RequestMapping(value = "/insert", method = RequestMethod.POST)
    public ResponseResult insertDeviceList(@RequestBody DeviceList deviceList) throws IOException, SQLException {
        //新增属性信息
        String deviceCode=deviceList.getDeviceCode();
        String productId=deviceList.getPdtCode();
        String status=deviceList.getStatus();//获取新增时候的状态
        //新增设备信息
        deviceList.setStatus("inactive");//新增设备默认未激活
        deviceList.setAlarmStatus(5);//新增未知状态
        Integer code  = deviceListService.insertDeviceList(deviceList);

        DeviceAttrValue deviceAttrValue=new DeviceAttrValue();
        deviceAttrValue.setDeviceCode(deviceCode);//设备code
        deviceAttrValue.setPdtCode(productId);
        deviceAttrValue.setAttValue(0);//设置默认值为0
        //获取关联属性
        deviceAttValueService.insertDeviceAtt(deviceAttrValue);
        ResponseResult responseResult;
        if (code == RspStatusEnum.FAIL.getCode()) {
            responseResult = new ResponseResult(RspStatusEnum.FAIL.getCode(),"设备编码字段重复，请重新输入!",code.toString());
        } else {
            //新增成功后需要订阅topic信息
            if(status.equals("active")) {//如果新增的时候设备选择了激活，则需要发送
                readDeviceInfo(productId, deviceCode);
            }
            responseResult = new ResponseResult(RspStatusEnum.SUCCESS.getCode(),RspStatusEnum.SUCCESS.getMessage(),code.toString());
        }
        return responseResult;
    }


    /**
     * 删除设备
     *
     * @param ids 设备ID,满足批量删除
     * @return
     */

    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public ResponseResult deleteDeviceList(@RequestBody JSONObject ids)  throws IOException {
        JSONArray jsonArray = ids.getJSONArray("ids");
        List<Long> idList = JSONObject.parseArray(jsonArray.toJSONString(), Long.class);
        //删除设备属性值
        for(Long id:idList) {
            DeviceList deviceList= deviceListService.queryOneDevice(id);
            deviceAttValueService.deleteDeviceAtt(deviceList.getDeviceCode());
        }
        //然后删除设备
        Integer code  = deviceListService.deleteDeviceList(idList);
        ResponseResult responseResult;
        if (code == RspStatusEnum.FAIL.getCode()) {
            responseResult = new ResponseResult(RspStatusEnum.FAIL.getCode(),"该设备还包含属性信息，无法删除!",code.toString());
        } else {
            responseResult = new ResponseResult(RspStatusEnum.SUCCESS.getCode(),RspStatusEnum.SUCCESS.getMessage(),code.toString());
        }
        return responseResult;
    }



    /**
     * 新增后发送mqtt的read接口获取配置属性的初始化值
     */
    @RequestMapping(value = "/readDeviceInfo", method = RequestMethod.POST)
    private void readDeviceInfo(@RequestParam(value="ProductId", required=true) String ProductId,
                                @RequestParam(value="DeviceId", required=true) String DeviceId) {
        //Properties存放属性字段，格式：sn,model
        Map paramMp = new HashMap();
        String topic = "/" + ProductId + "/" + DeviceId + "/properties/read";
        Long currentTime = System.currentTimeMillis();
        UUID uuid = UUID.randomUUID();
        String messageId = uuid.toString();

        //属性需要加上“”，通过设备获取属性
        QueryWrapper qw = new QueryWrapper();
        qw.eq("device_code", DeviceId);
        List<DeviceAttrValue> deviceAttrValueList = deviceAttValueMapper.selectList(qw);
        int len = deviceAttrValueList.size();
        String[] Properties = new String[len];
        for (int i = 0; i < len; i++) {
            Properties[i] = deviceAttrValueList.get(i).getAttCode();
        }
        paramMp.put("timestamp", currentTime);
        paramMp.put("messageId", messageId);
        paramMp.put("deviceId", DeviceId);
        paramMp.put("properties", Properties);

        String message = JSONObject.toJSONString(paramMp, SerializerFeature.WriteMapNullValue);
        System.out.println("========read========" + message);
        //发送/{productId}/{deviceId}/properties/read 读取设备属性
        iMqttSender.sendToMqtt(topic, message);

        MqttLog mqttLog = new MqttLog();
        //保存发送日志
        long id = idServiceHelper.nextId();
        mqttLog.setMqttLogId(id);
        mqttLog.setTopic(topic);
        mqttLog.setMessage(message);
        mqttLog.setMessageId(messageId);
        mqttLog.setTimestamp(currentTime);
        mqttLog.setSendTime(DateUtils.getDateTimeNowStr());
        mqttLogService.insertAction(mqttLog);

        //并且订阅read/reply
//        MqttSubSys mqttSubSys=new MqttSubSys();
//        mqttSubSys.init();
//        subscribe("new_readReplyClient"+new Random().nextInt(100),topic);
//        try {
//            MqttClient client= new MqttClient("tcp://118.195.176.189:1883", "new_receiverClient"+new Random().nextInt(100), new MemoryPersistence());
//            //如果是订阅者则添加回调类，发布不需要
//            client.setCallback(new NewCallBackSys());
//            MqttConnectOptions options = new MqttConnectOptions();
//            //会话清除标识session
//            options.setCleanSession(false);
//            options.setUserName("admin");
//            options.setPassword("public".toCharArray());
//            //设置超时时间
//            options.setConnectionTimeout(10);
//            //设置心跳
//            options.setKeepAliveInterval(20);
//            //判断拦截状态，这里注意一下，如果没有这个判断，是非常坑的
//            if (!client.isConnected()) {
//                client.connect(options);
//            } else {
//                client.disconnect();
//                client.connect(options);
//            }
//            client.subscribe(topic+"/reply",1);
//        }catch (MqttException e){
//            e.printStackTrace();
//        }

    }

    private void writeDeviceInfo(String ProductId, String DeviceId,Map Properties) {
        //Properties存放属性字段
        Map paramMp = new HashMap();

        String topic = "/" + ProductId + "/" + DeviceId + "/properties/write";
        Long currentTime = System.currentTimeMillis();
        UUID uuid = UUID.randomUUID();
        String messageId = uuid.toString();

        paramMp.put("timestamp", currentTime);
        paramMp.put("messageId", messageId);
        paramMp.put("deviceId", DeviceId);
        paramMp.put("properties", Properties);

        String message = JSONObject.toJSONString(paramMp, SerializerFeature.WriteMapNullValue);
        System.out.println("=======write=========" + message);
        //调用topic，发送mqtt的write接口，还需要加上订阅接口reply
        iMqttSender.sendToMqtt(topic, message);

        MqttLog mqttLog = new MqttLog();
        //保存发送日志
        long id = idServiceHelper.nextId();
        mqttLog.setMqttLogId(id);
        mqttLog.setTopic(topic);
        mqttLog.setMessage(message);
        mqttLog.setMessageId(messageId);
        mqttLog.setTimestamp(currentTime);
        mqttLog.setSendTime(DateUtils.getDateTimeNowStr());
        mqttLogService.insertAction(mqttLog);

        //订阅/properties/write/reply
        //并且订阅read/reply topic
//        subscribe("new_writeReplyClient"+new Random().nextInt(100),topic);
    }

//    private void subscribe(String clientId,String topic){
//        //并且订阅read/reply topic
//        try {
//            MqttClient client= new MqttClient(HOST, clientId, new MemoryPersistence());
//            //如果是订阅者则添加回调类，发布不需要
//            client.setCallback(new NewCallBackSys());
//            MqttConnectOptions options = new MqttConnectOptions();
//            //会话清除标识session
//            options.setCleanSession(false);
//            options.setUserName(username);
//            options.setPassword(password.toCharArray());
//            //设置超时时间
//            options.setConnectionTimeout(10);
//            //设置心跳
//            options.setKeepAliveInterval(20);
//            //判断拦截状态，这里注意一下，如果没有这个判断，是非常坑的
//            if (!client.isConnected()) {
//                client.connect(options);
//            } else {
//                client.disconnect();
//                client.connect(options);
//            }
//            //订阅read或者write的reply
//            client.subscribe(topic+"/reply",1);
//            //并且订阅report event
//            String[] other=topic.split("/");
//            client.subscribe("/"+other[1]+"/"+other[2]+"/properties/report",1);
//            client.subscribe("/"+other[1]+"/"+other[2]+"/event/sensorAlarm",1);
//        }catch (MqttException e){
//            e.printStackTrace();
//        }
//    }

}
